#!/usr/bin/env bash
# Creates Linux ".AppImage" for @PROJECT_NAME_UCASE@
#
# Depends:  linuxdeployqt
#
# Notes:    Will attempt to fetch linuxdeployqt automatically (x86_64 only)
#           See Also: https://github.com/probonopd/linuxdeployqt/blob/master/BUILDING.md

VERBOSITY=2 # 3=debug
LOGFILE="@CMAKE_BINARY_DIR@/appimage.log"
APPDIR="@CMAKE_BINARY_DIR@/@PROJECT_NAME_UCASE@.AppDir/"
DESKTOPFILE="${APPDIR}usr/share/applications/lmms.desktop"
STRIP=""

# Don't strip for Debug|RelWithDebInfo builds
# shellcheck disable=SC2193
if [[ "@CMAKE_BUILD_TYPE@" == *"Deb"* ]]; then
	STRIP="-no-strip"
fi

# Console colors
RED="\\x1B[1;31m"
GREEN="\\x1B[1;32m"
YELLOW="\\x1B[1;33m"
PLAIN="\\x1B[0m"

function error {
	echo -e "   ${PLAIN}[${RED}error${PLAIN}] ${1}"
	return 1
}

function success {
	echo -e "   ${PLAIN}[${GREEN}success${PLAIN}] ${1}"
}

function skipped {
	echo -e "   ${PLAIN}[${YELLOW}skipped${PLAIN}] ${1}"
}

# Exit with error message if any command fails
trap "error 'Failed to generate AppImage'; exit 1" ERR

# Run a command silently, but print output if it fails
function run_and_log {
	echo -e "\n\n>>>>> $1" >> "$LOGFILE"
	output="$("$@" 2>&1)"
	status=$?
	echo "$output" >> "$LOGFILE"
	[[ $status != 0 ]] && echo "$output"
	return $status
}

# Blindly assume system arch is appimage arch
ARCH=$(uname -m)
export ARCH

# Check for problematic install locations
INSTALL=$(echo "@CMAKE_INSTALL_PREFIX@" | sed 's/\/*$//g')
if [ "$INSTALL" == "/usr/local" ] || [ "$INSTALL" == "/usr" ] ; then
	error "Incompatible CMAKE_INSTALL_PREFIX for creating AppImage: @CMAKE_INSTALL_PREFIX@"
fi

# Ensure linuxdeployqt uses the same qmake version as cmake
PATH="$(dirname "@QT_QMAKE_EXECUTABLE@"):$PATH"
export PATH

# Use linuxdeployqt from env or in PATH
[[ $LINUXDEPLOYQT ]] || LINUXDEPLOYQT="$(which linuxdeployqt 2>/dev/null)" || true
[[ $APPIMAGETOOL ]] || APPIMAGETOOL="$(which appimagetool 2>/dev/null)" || true

# Fetch portable linuxdeployqt if not in PATH
if [[ -z $LINUXDEPLOYQT || -z $APPIMAGETOOL ]]; then
	filename="linuxdeployqt-continuous-$ARCH.AppImage"
	url="https://github.com/probonopd/linuxdeployqt/releases/download/continuous/$filename"
	echo "   [.......] Downloading: ${url}"
	wget -N -q "$url" && err=0 || err=$?
	case "$err" in
		0) success "Downloaded $PWD/$filename" ;;
		# 8 == server issued 4xx error
		8) error "Download failed (perhaps no package available for $ARCH)" ;;
		*) error "Download failed" ;;
	esac

	# Extract AppImage and replace LINUXDEPLOYQT variable with extracted binary
	# to support systems without fuse
	# Also, we need to set LD_LIBRARY_PATH, but linuxdepoyqt's AppRun unsets it
	# See https://github.com/probonopd/linuxdeployqt/pull/370/
	chmod +x "$filename"
	./"$filename" --appimage-extract >/dev/null
	success "Extracted $filename"

	# Use the extracted linuxdeployqt and appimagetool
	PATH="$(pwd -P)/squashfs-root/usr/bin:$PATH"
	[[ $LINUXDEPLOYQT ]] || LINUXDEPLOYQT="$(which linuxdeployqt)"
	[[ $APPIMAGETOOL ]] || APPIMAGETOOL="$(which appimagetool)"
fi

# Make skeleton AppDir
echo -e "\nCreating ${APPDIR}..."
rm -rf "${APPDIR}"
mkdir -p "${APPDIR}usr"
success "Created ${APPDIR}"

# Clone install to AppDir
echo -e "\nCopying @CMAKE_INSTALL_PREFIX@ to ${APPDIR}..."
cp -R "@CMAKE_INSTALL_PREFIX@/." "${APPDIR}usr"
rm -rf "${APPDIR}usr/include"
success "${APPDIR}"

# Copy rawwaves directory for stk/mallets
mkdir -p "${APPDIR}usr/share/stk/"
cp -R /usr/share/stk/rawwaves/ "${APPDIR}usr/share/stk/"

# Create a wrapper script which calls the lmms executable
mv "${APPDIR}usr/bin/lmms" "${APPDIR}usr/bin/lmms.real"

cp "@CMAKE_CURRENT_SOURCE_DIR@/launch_lmms.sh" "${APPDIR}usr/bin/lmms"

chmod +x "${APPDIR}usr/bin/lmms"

# Per https://github.com/probonopd/linuxdeployqt/issues/129
unset LD_LIBRARY_PATH

# Ensure linuxdeployqt can find shared objects
export LD_LIBRARY_PATH="${APPDIR}"usr/lib/lmms/:"${APPDIR}"usr/lib/lmms/optional:"$LD_LIBRARY_PATH"

# Move executables so linuxdeployqt can find them
ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx"
VSTLIB32="${APPDIR}usr/lib/lmms/32/RemoteVstPlugin32.exe.so"
VSTLIB64="${APPDIR}usr/lib/lmms/RemoteVstPlugin64.exe.so"

ZYNBIN="${APPDIR}usr/bin/RemoteZynAddSubFx"
VSTBIN32="${APPDIR}usr/bin/RemoteVstPlugin32.exe.so"
VSTBIN64="${APPDIR}usr/bin/RemoteVstPlugin64.exe.so"

mv "$ZYNLIB" "$ZYNBIN"
mv "$VSTLIB32" "$VSTBIN32" || true
mv "$VSTLIB64" "$VSTBIN64" || true

# Handle wine linking
if [ -d "@WINE_32_LIBRARY_DIR@" ] && \
		ldd "$VSTBIN32" | grep "libwine\.so" | grep "not found"; then
   export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"@WINE_32_LIBRARY_DIRS@"
fi
if [ -d "@WINE_64_LIBRARY_DIR@" ] && \
		ldd "$VSTBIN64" | grep "libwine\.so" | grep "not found"; then
   export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"@WINE_64_LIBRARY_DIRS@"
fi

# Patch the desktop file
sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE"
echo "X-AppImage-Version=@VERSION@" >> "$DESKTOPFILE"

# Fix linking for soft-linked plugins
for file in "${APPDIR}usr/lib/lmms/"*.so; do
   thisfile="${APPDIR}usr/lib/lmms/${file##*/}"
   executables="${executables} -executable=$thisfile"
done
executables="${executables} -executable=${ZYNBIN}"
executables="${executables} -executable=${VSTBIN32}"
executables="${executables} -executable=${VSTBIN64}"
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imp_1199.so"
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/imbeq_1197.so"
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1193.so"
executables="${executables} -executable=${APPDIR}usr/lib/lmms/ladspa/pitch_scale_1194.so"

echo -e "\nWriting verbose output to \"${LOGFILE}\""
echo -n > "$LOGFILE"

# Bundle both qt and non-qt dependencies into appimage format
echo -e "\nBundling and relinking system dependencies..."

# shellcheck disable=SC2086
run_and_log "$LINUXDEPLOYQT" "$DESKTOPFILE" $executables -bundle-non-qt-libs -verbose=$VERBOSITY $STRIP
success "Bundled and relinked dependencies"

# Link to original location so lmms can find them
ln -sr  "$ZYNBIN" "$ZYNLIB"
ln -sr  "$VSTBIN32" "$VSTLIB32" || true
ln -sr  "$VSTBIN64" "$VSTLIB64" || true

# Remove wine library conflict
rm -f "${APPDIR}/usr/lib/libwine.so.1"

# Use system-provided carla
rm -f "${APPDIR}usr/lib/"libcarla*.so
rm -f "${APPDIR}usr/lib/lmms/optional/"libcarla*.so

# Remove bundled jack in LD_LIBRARY_PATH if exists
if [ -e "${APPDIR}/usr/lib/libjack.so.0" ]; then
   rm "${APPDIR}/usr/lib/libjack.so.0"
fi

# Bundle jack out of LD_LIBRARY_PATH
JACK_LIB=$(ldd "${APPDIR}/usr/bin/lmms.real" | sed -n 's/\tlibjack\.so\.0 => \(.\+\) (0x[0-9a-f]\+)/\1/p')
if [ -e "$JACK_LIB" ]; then
   mkdir -p "${APPDIR}usr/lib/lmms/optional/"
   cp "$JACK_LIB" "${APPDIR}usr/lib/lmms/optional/"
fi

# Point the AppRun to the shim launcher
rm -f "${APPDIR}/AppRun"
ln -sr "${APPDIR}/usr/bin/lmms" "${APPDIR}/AppRun"

# Add icon
ln -srf "${APPDIR}/lmms.png" "${APPDIR}/.DirIcon"

# Create AppImage
echo -e "\nFinishing the AppImage..."
run_and_log "$APPIMAGETOOL" "${APPDIR}" "@APPIMAGE_FILE@"
success "Created @APPIMAGE_FILE@"

echo -e "\nFinished"
